sequenceDiagram
        actor UserA
        participant MsClientA
        participant PeerA
        participant Server
        participant PeerB
        participant MsClientB
        actor UserB
        # 登录阶段
        Note over UserA,UserB: === 登录阶段 ===
        UserA->>PeerA: login
        PeerA->>Server: loginReq(userId/token)
        Server-->>PeerA: loginRes(users)
        UserB->>PeerB: login
        PeerB->>Server: loginReq(userId/token)
        Server-->>PeerB: loginRes(users)

        # 呼叫阶段
        Note over UserA,UserB: === 呼叫阶段 ===
        # 本端
        UserA->>PeerA: makeCall(userId, mediaTypes)
        PeerA->>UserA: connecting
        PeerA->>Server: prepareRoomReq(roomId)
        Server-->>PeerA: prepareRoomRes(rtpCapabilities)
        PeerA->>MsClientA: Load(rtpCapabilities)
        PeerA->>MsClientA: GetCapabilities
        PeerA->>Server: joinRoomReq(roomId,rtpCapabilities)
        Server-->>PeerA: joinRoomRes(roomUsers)
        Note right of Server: including user's producer
        PeerA->>MsClientA: GetSctpCapabilities
        PeerA->>Server: createTransportReq
        Note left of PeerA: forceTcp<br>producing<br>consuming<br>sctpCapabilities      
        Server-->>PeerA: createTransportRes
        Note right of Server: iceParameters<br>iceCandidates<br>dtlsParameters
        PeerA->>MsClientA: CreateTransport
        PeerA->>Server: callMakeReq(userId, roomId)
        # 远端
        Server->>PeerB: callMakeNotify(roomId)
        UserB->>PeerB: acceptCall
        PeerB->>UserB: connecting
        PeerB->>Server: prepareRoomReq(roomId)
        Server-->>PeerB: prepareRoomRes(rtpCapabilities)
        PeerB->>MsClientB: Load(rtpCapabilities)
        PeerB->>MsClientB: GetCapabilities
        PeerB->>Server: joinRoomReq(roomId, rtpCapabilities)
        Server-->>PeerB: joinRoomRes(roomUsers)
        Note left of Server: including user's producer
        PeerB->>MsClientB: getSctpCapabilities
        PeerB->>Server: createTransportReq
        Note right of PeerB: forceTcp<br>producing<br>consuming<br>sctpCapabilities  
        Server-->>PeerB: createTransportRes(...)
        Note left of Server: iceParameters<br>iceCandidates<br>dtlsParameters
        PeerB->>UserB: connected
        PeerB-->>Server: callMakeAck
        Server-->>PeerA: callMakeRes
        PeerA->>UserA: connected

        # 发布阶段
        Note over UserA,UserB: === 发布阶段 ===
        UserA->>PeerA: publish(media)
		PeerA->>MsClientA: Produce
        MsClientA->>PeerA: OnConnect
        PeerA->>Server: connectTransportReq
        Note left of PeerA: transportId<br>iceParameters<br>dtlsParameters
        Server-->>PeerA: connectTransportRes
        PeerA-->>MsClientA: return
        MsClientA->>PeerA: OnProduce
        PeerA->>Server: createProducerReq
        Note left of PeerA: transportId<br>kind<br>rtpParameters<br>appData
        Server-->>PeerA: createProducerRes(producerId)
        PeerA-->>MsClientA: return
        PeerA->>Server: publishReq
        Server-->>PeerA: publishRes
        Server->>PeerB: publishNotify
        PeerB-->>Server: publishAck

        # 订阅阶段
        Note over UserA,UserB: === 订阅阶段 ===
        UserB->>PeerB: subscribe
        PeerB->>Server: subscribeReq
        Server->>PeerA: startProduceNotify
		PeerA->>MsClientA: Resume
		PeerA-->>Server: startProduceAck
        Server-->>PeerB: subscribeRes
        Note left of Server: consumerId<br>rtpParameters
        PeerB->>MsClientB: Consume
        MsClientB->>PeerB: OnConnect
        PeerB->>Server: connectTransportReq
        Note right of PeerB: transportId<br>iceParameters<br>dtlsParameters
        Server-->>PeerB: connectTransportRes
        PeerB-->>MsClientB: return
        PeerB->>Server: resumeReq(consumerId)
        Server-->>PeerB: resumeRes
